<template>
    <div class="cvu-upload">
        <!-- 默认上传 -->
        <div class="cvu-upload-body" v-if="uploadType === 'image' || uploadType === 'file'">
            <Upload
                ref="upload"
                :headers="headers"
                :action="action"
                :multiple="multiple"
                :type="type"
                :show-upload-list="showUploadList"
                :disabled="disabled"
                :data="data"
                :name="name"
                :accept="accept"
                :format="newFormat"
                :maxSize="maxSize"
                :before-upload="beforeUpload"
                :on-exceeded-size="handleMaxSize"
                :on-format-error="handleFormatError"
                :on-remove="handleRemove"
                :on-success="handleSuccess"
                :on-error="handleError"
            >
                <slot></slot>
            </Upload>
        </div>
        <!-- 自定义列表上传（用于多图上传，显示上传图片列表） -->
        <div class="cvu-upload-body" v-if="uploadType === 'list'">
            <div class="cvu-upload-list" v-for="(item, index) in fileList" :key="index">
                <template v-if="item.status === 'finished'">
                    <img :src="item.url" alt="">
                    <div class="cvu-upload-list-cover">
                        <Icon type="ios-eye-outline" @click.native="handlePreview(item, index)"></Icon>
                        <Icon type="ios-trash-outline" @click.native="handleDelete(item, index)"></Icon>
                    </div>
                </template>
                <template v-else>
                    <Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
                </template>
            </div>
            <Upload
                ref="upload"
                :headers="headers"
                :action="action"
                :multiple="multiple"
                :type="type"
                :show-upload-list="showUploadList"
                :default-file-list="defaultFileList"
                :disabled="disabled"
                :data="data"
                :name="name"
                :accept="accept"
                :format="newFormat"
                :maxSize="maxSize"
                :before-upload="beforeUpload"
                :on-exceeded-size="handleMaxSize"
                :on-format-error="handleFormatError"
                :on-remove="handleRemove"
                :on-success="handleSuccess"
                :on-error="handleError"
            >
                <div class="cvu-upload-add" v-if="this.fileList.length < this.maxLength">
                    <Icon type="md-add" />
                </div>
            </Upload>
        </div>
        <cvu-preview 
            :show="previewConfig.show" 
            :currentIndex="previewConfig.currentIndex"
            :files="previewConfig.files"
            @on-close="handlePreviewClose"
        ></cvu-preview>
    </div>
</template>
<script>
export default {
    name: 'cvu-upload',
    props: {
        // 上传文件类型 可选值 image：图片上传 | list：图片列表上传 | file：文件上传
        uploadType: {
            type: String,
            default: 'image'
        },
        // 设置上传的请求头部
        headers: {
            type: Object,
            default: () => {}
        },
        // 上传的地址，必填
        action: {
            type: String,
            default: ''
        },
        // 是否支持多选文件
        multiple: {
            type: Boolean,
            default: false
        },
        // 上传控件的类型，可选值为 select（点击选择），drag（支持拖拽）
        type: {
            type: String,
            default: 'select'
        },
        // 是否显示默认格式已上传文件列表
        showUploadList: {
            type: Boolean,
            default: false
        },
        // 是否禁用
        disabled: {
            type: Boolean,
            default: false
        },
        // 上传时附带的额外参数
        data: {
            type: Object,
            default: () => {}
        },
        // 上传的文件字段名
        name: {
            type: String,
            default: 'file'
        },
        // 接受上传的文件类型
        accept: {
            type: String,
            default: ''
        },
        // 支持的文件类型，与 accept 不同的是，format 是识别文件的后缀名，accept 为 input 标签原生的 accept 属性，会在选择文件时过滤，可以两者结合使用
        format: {
            type: Array,
            default: () => []
        },
        // 文件大小限制，单位 kb
        maxSize: {
            type: Number,
            default: 2048
        },
        // 文件数量限制
        maxLength: {
            type: Number,
            default: 5
        },
        // 默认已上传的文件列表
        defaultFileList: {
            type: Array,
            default: () => []
        }
    },
    data() {
        return {
            // 文件类型
            newFormat: ['jpg', 'jpeg', 'png'],
            fileList: [],
            // 图片预览配置
            previewConfig: {
                show: false,
                currentIndex: 0,
                files: []
            }
        }
    },
    watch: {
        format: {
            handler(newFormat = [], oldFormat) {
                this.newFormat = newFormat.length ? newFormat : ['jpg', 'jpeg', 'png']
            },
            immediate: true
        },
        uploadType: {
            handler(newUploadType, oldUploadType) {
                if(newUploadType === 'image' || newUploadType === 'list') {
                    this.newFormat = ['jpg', 'jpeg', 'png']
                } 
                if(newUploadType === 'file') {
                    this.newFormat = [
                        'docx', 'doc', 'docm', 'dot', 'dotx',
                        'xl', 'xls', 'xlsx', 'xla', 'xlam', 'xlsm', 'xlt', 'xltm', 'xltx', 'xll', 'xlm', 'xla',
                        'pdf'
                    ]
                }
            },
            immediate: true
        }
    },
    mounted() {
        this.fileList = this.$refs.upload.fileList || []
    },
    methods: {
        // 上传文件之前的钩子，参数为上传的文件，若返回 false 或者 Promise 则停止上传
        beforeUpload() {
            if(this.fileList.length + 1 > this.maxLength) {
                this.$Message['warning']({
                    background: true,
                    content: `最多上传${this.maxLength}份文件`
                })
                return this.fileList.length > this.maxLength
            }
            this.$emit('before-upload')
        },
        // 文件超出指定大小限制时的钩子，返回字段为 file, fileList
        handleMaxSize(file, fileList) {
            this.$Message['error']({
                background: true,
                content: `上传尺寸最大${this.maxSize}kb`
            })
            this.$emit('on-exceeded-size', { file: file, fileList: fileList })
        },
        // 文件格式验证失败时的钩子，返回字段为 file, fileList
        handleFormatError(file, fileList) {
            this.$Message['error']({
                background: true,
                content: `请上传${this.newFormat.join('、')}格式的文件`
            })
            this.$emit('on-format-error', { file: file, fileList: fileList })
        },
        // 文件列表移除文件时的钩子，返回字段为 file, fileList
        handleRemove(file, fileList) {
            this.$Message['success']({
                background: true,
                content: '删除成功'
            })
            this.$emit('on-remove', { file: file, fileList: fileList })
        },
        // 文件上传成功时的钩子，返回字段为 response, file, fileList
        handleSuccess(res, file, fileList) {
            this.$Message['success']({
                background: true,
                content: '上传成功'
            })
            this.$emit('on-success', { res: res, file: file, fileList: fileList })
        },
        // 文件上传失败时的钩子，返回字段为 error, file, fileList
        handleError(error, file, fileList) {
            this.$Message['error']({
                background: true,
                content: '上传失败'
            })
            this.$emit('on-error', { error: error, file: file, fileList: fileList })
        },
        // 图片预览
        handlePreview(item, index) {
            this.previewConfig = {
                show: true,
                files: [item]
            }
        },
        // 关闭图片预览
        handlePreviewClose() {
            this.previewConfig = {
                show: false,
                files: []
            }
        },
        // 图片列表删除
        handleDelete(item, index) {
            const fileList = this.$refs.upload.fileList
            this.$refs.upload.fileList.splice(fileList.indexOf(item), 1)
            this.$emit('on-remove', { file: item, fileList: this.fileList })
        }
    }
}
</script>
<style lang="scss" scoped>
    @import '../../../style/_index.scss';
    .cvu-upload{
        display: inline-block;
        vertical-align: middle;
    }
    .cvu-upload-body{
        display: inline-block;
        vertical-align: middle;
    }
    .ivu-upload{
        display: inline-block;
        vertical-align: middle;
    }
    .cvu-upload-list{
        display: inline-block;
        vertical-align: middle;
        width: 80px;
        height: 80px;
        text-align: center;
        line-height: 80px;
        border: 1px solid transparent;
        border-radius: 6px;
        overflow: hidden;
        background: #fff;
        position: relative;
        box-shadow: 0 1px 1px rgba(0,0,0,.2);
        margin-right: 10px;
    }
    .cvu-upload-list img{
        width: 100%;
        height: 100%;
    }
    .cvu-upload-list-cover{
        display: none;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        background: rgba(0,0,0,.6);
    }
    .cvu-upload-list:hover .cvu-upload-list-cover{
        display: block;
    }
    .cvu-upload-list-cover i{
        color: #fff;
        font-size: 20px;
        cursor: pointer;
        margin: 0 2px;
    }
    .cvu-upload-add{
        display: inline-block;
        vertical-align: middle;
        width: 80px;
        height: 80px;
        text-align: center;
        line-height: 80px;
        border: 1px dashed #CDCDCD;
        border-radius: 6px;
        overflow: hidden;
        background: #fff;
        position: relative;
        cursor: pointer;
        i{
            font-size: 26px;
            color: #999;
        }
    }
</style>